package com.night.icm.service.base.service;

import com.github.wenhao.jpa.PredicateBuilder;
import com.github.wenhao.jpa.Specifications;
import com.night.icm.common.exception.NoSuchDataException;
import com.night.icm.common.jpa.PageHelper;
import com.night.icm.common.service.PageDataUtil;
import com.night.icm.common.utils.PageDataDTO;
import com.night.icm.common.utils.SimpleDataDTO;
import com.night.icm.model.base.CourseDTO;
import com.night.icm.persistence.base.entity.Course;
import com.night.icm.persistence.base.entity.CourseType;
import com.night.icm.persistence.base.repository.CourseRepository;
import com.night.icm.persistence.base.repository.CourseTypeRepository;
import com.night.icm.service.base.mapper.CourseMapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Optional;

/**
 * CourseServiceImpl
 *
 * @author Liao ZhiYong
 * @date 2020/2/7
 */
@Service
@Transactional(readOnly = true, rollbackFor = Exception.class)
public class CourseServiceImpl implements CourseService {

    private final CourseRepository courseRepository;
    private final CourseMapper courseMapper;
    private final CourseTypeRepository courseTypeRepository;

    @Autowired
    public CourseServiceImpl(CourseRepository courseRepository, CourseMapper courseMapper, CourseTypeRepository courseTypeRepository) {
        this.courseRepository = courseRepository;
        this.courseMapper = courseMapper;
        this.courseTypeRepository = courseTypeRepository;
    }

    /**
     * 分页查询课程
     *
     * @param page           页号，从0开始
     * @param size           每页记录条数
     * @param sort           排序字段，例如：字段1,asc,字段2,desc
     * @param code           课程编号
     * @param name           课程名称
     * @param courseTypeId   课程类型
     * @param evaluationMode 考核方式
     * @return
     */
    @Override
    public PageDataDTO<CourseDTO> findOnePage(int page, int size, String sort, String code, String name, String courseTypeId, String evaluationMode) {
        PredicateBuilder<Course> pb = Specifications.<Course>and()
                .like(StringUtils.isNotBlank(code), "code", "%" + code + "%")
                .like(StringUtils.isNotBlank(name), "name", "%" + name + "%")
                .eq(StringUtils.isNotBlank(courseTypeId), "courseType.id", courseTypeId)
                .eq(StringUtils.isNotBlank(evaluationMode), "evaluationMode", evaluationMode);
        Page<Course> page1 = this.courseRepository.findAll(pb.build(), PageHelper.generatePageRequest(page, size, sort));
        List<CourseDTO> dtos = this.courseMapper.toList(page1.getContent());
        return PageDataUtil.toPageData(page1, dtos);
    }

    /**
     * 新增课程
     *
     * @param courseDTO 课程类型信息
     * @return 课程类型信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public CourseDTO create(CourseDTO courseDTO) {
        Course course = this.courseMapper.toEntity(courseDTO);
        String courseTypeId = courseDTO.getCourseType().getId();
        Optional<CourseType> courseTypeOptional = this.courseTypeRepository.findById(Long.valueOf(courseTypeId));
        if (!courseTypeOptional.isPresent()) {
            throw new NoSuchDataException(courseTypeId);
        }
        CourseType courseType = courseTypeOptional.get();
        course.setCourseType(courseType);
        Course save = this.courseRepository.save(course);
        return this.courseMapper.toDTO(save);
    }

    /**
     * 删除课程
     *
     * @param id 删除课程id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(String id) {
        this.courseRepository.deleteById(Long.valueOf(id));
    }

    /**
     * 更新课程信息
     *
     * @param id        课程id
     * @param courseDTO 课程信息
     * @return 课程信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public CourseDTO update(String id, CourseDTO courseDTO) {
        Course course = this.getOne(id);
        this.courseMapper.updateEntity(courseDTO, course);
        this.courseRepository.save(course);
        return this.courseMapper.toDTO(course);
    }

    /**
     * 根据id查找课程类型信息
     *
     * @param id id
     * @return 课程类型信息
     */
    @Override
    public CourseDTO findById(String id) {
        Course course = this.getOne(id);
        return this.courseMapper.toDTO(course);
    }

    /**
     * 根据id查找课程类型信息
     *
     * @param id 课程id
     * @return 课程
     */
    private Course getOne(String id) {
        Optional<Course> courseOptional = this.courseRepository.findById(Long.valueOf(id));
        if (!courseOptional.isPresent()) {
            throw new NoSuchDataException(id);
        }
        return courseOptional.get();
    }
    /**
     * 查找所有课程信息，可选择排序
     *
     * @param param   排序参数
     * @param pattern 排序模式: asc/desc
     * @return 课程信息
     */
    @Override
    public List<CourseDTO> findAll(String param, String pattern) {
        String keyType = "asc";
        Sort sort;
        if (keyType.equals(pattern)) {
            sort = new Sort(Sort.Direction.ASC, param);
        } else {
            sort = new Sort(Sort.Direction.DESC, param);
        }
        List<Course> all = this.courseRepository.findAll(sort);
        return this.courseMapper.toList(all);
    }

    /**
     * 检查课程编号是否已存在
     *
     * @param code code
     * @return 检查课程编号是否已存在
     */
    @Override
    public SimpleDataDTO<Boolean> checkCodeExist(String code) {
        SimpleDataDTO<Boolean> simpleDataDTO = new SimpleDataDTO<>();
        Course byCode = this.courseRepository.findByCode(code);
        simpleDataDTO.setData(byCode != null);
        return simpleDataDTO;
    }
}